package com.kmxd.ams.infra.logs.aop;

import com.baomidou.mybatisplus.core.toolkit.SystemClock;
import com.kmxd.ams.core.log.annotation.ArchLogParameter;
import com.kmxd.ams.core.log.annotation.ArchLogParameters;
import java.util.Objects;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Service;

/**
 * 日志注解
 *
 * @author admin
 */
@Slf4j
@Aspect
@Service("ArchLogAspect")
public class ArchLogAspect {

  @Autowired private LogsCmd logsCmd;

  @Pointcut(
      "@annotation(com.kmxd.ams.core.log.annotation"
          + ".ArchLogParameter)||@annotation(com.kmxd.ams.core.log.annotation.ArchLogParameters)")
  public void logPointCut() {}

  @Around("logPointCut()")
  @SneakyThrows
  public Object around(ProceedingJoinPoint point) {
    long startTime = SystemClock.now();
    Object obj = null;
    Exception exception = null;
    try {
      obj = point.proceed();
    } catch (Exception e) {
      exception = e;
      throw e;
    } finally {
      long endTime = SystemClock.now();
      handleLog(point, exception, obj, endTime - startTime);
    }
    return obj;
  }

  protected void handleLog(
      final JoinPoint joinPoint, final Exception e, Object retValue, long time) {
    try {
      // 获得注解
      Signature signature = joinPoint.getSignature();
      MethodSignature methodSignature = (MethodSignature) signature;

      ArchLogParameters logs =
          AnnotationUtils.findAnnotation(methodSignature.getMethod(), ArchLogParameters.class);
      if (Objects.nonNull(logs)) {
        for (ArchLogParameter autoLog : logs.value()) {
          saveLog(autoLog, joinPoint, e, retValue, time);
        }
      } else {
        ArchLogParameter autoLog =
            AnnotationUtils.findAnnotation(methodSignature.getMethod(), ArchLogParameter.class);
        saveLog(autoLog, joinPoint, e, retValue, time);
      }
    } catch (Exception exception) {
      log.error("异常信息:{}", exception.getMessage());
      exception.printStackTrace();
    }
  }

  private void saveLog(
      ArchLogParameter autoLog, JoinPoint joinPoint, Exception e, Object retValue, long time) {
    if (Objects.isNull(autoLog)) {
      return;
    }
    logsCmd.logsArchive(autoLog, joinPoint, e, retValue, time);
  }
}
